#include "client.h"
#include "level.h"

Client::Client()
{
	printf("SOMETHING WENT HORRIBLY WRONG!");
}

Client::Client(int id, std::string name, std::string sname, int x, int y, int z, char rx, char ry, TCPsocket socket, bool admin)
{
	this->id = id;
	this->name = name;
	this->sname = sname;
	this->x = this->ox = x;
	this->y = this->oy = y;
	this->z = this->oz = z;
	this->rx = this->orx = rx;
	this->ry = this->ory = ry;
	this->socket = socket;
	
	this->admin = admin;
	this->frozen = false;
	this->moved = false;
	this->mute = false;
	
	this->packet_size = 0;
	
	this->set_last_block(-1, 0,0,0, 1);
	this->set_last_block(-1, 0,0,0, 1);
}

Client::~Client() 
{

}

void Client::append_packet(char* buffer, int len) 
{
	if (this->packet_size + len >= 1024) {
		SDLNet_TCP_Send(this->socket, this->packet, this->packet_size);
		memset(this->packet, 0, 1024);
		this->packet_size = 0;
		this->append_packet(buffer, len);
	} else {
		memcpy(&this->packet[this->packet_size], buffer, len);
		this->packet_size += len;
	}
}

void Client::send_map(char* map, int len)
{
	char buffer[1024];
	buffer[0] = 02;
	SDLNet_TCP_Send(this->socket, buffer, 1);
	
	for ( int a = 0; ; ) {
		if (a + 1024 < len) {
			buffer[0] = 03;
			SDLNet_Write16(1024, &buffer[1]);
			SDLNet_TCP_Send(this->socket, buffer, 3);
			SDLNet_TCP_Send(this->socket, &map[a], 1024);
			buffer[0] = char(a / (len-4) * 100);
			SDLNet_TCP_Send(this->socket, buffer, 1);
			a += 1024;
		} else if (a + 1024 > len) {
			int l = len - a;
			buffer[0] = 03;
			SDLNet_Write16(l, &buffer[1]);
			SDLNet_TCP_Send(this->socket, buffer, 3);
			SDLNet_TCP_Send(this->socket, &map[a], l);
			int size = 1024-l;
			char* temp = new char[size];
			memset(temp, 0, size);
			SDLNet_TCP_Send(this->socket, temp, size);
			buffer[0] = 100;
			SDLNet_TCP_Send(this->socket, buffer, 1);
			delete [] temp;
			break;
		}
	}
}

int Client::send_packet()
{
	int ret = SDLNet_TCP_Send(this->socket, this->packet, this->packet_size);
	ret = ret < this->packet_size ? 1 : 0; 
	memset(this->packet, 0, 1024);
	this->packet_size = 0;
	return ret;
}

void Client::move(int x, int y, int z, int rx, int ry)
{
	this->set_pos(x,y,z,rx,ry);
	this->moved = true;
}

bool Client::isAdmin() 
{
	return this->admin;
}

bool Client::isFrozen()
{
	return this->frozen;
}

bool Client::isMoved()
{
	return this->moved;
}

void Client::get_pos(int* x, int* y, int* z, int* rx, int* ry)
{
	if (x != NULL) *x = this->x;
	if (y != NULL) *y = this->y;
	if (z != NULL) *z = this->z;
	if (rx != NULL) *rx = this->rx;
	if (ry != NULL) *ry = this->ry;
}

void Client::get_pos_old(int* x, int* y, int* z, int* rx, int* ry)
{
	if (x != NULL) *x = this->ox;
	if (y != NULL) *y = this->oy;
	if (z != NULL) *z = this->oz;
	if (rx != NULL) *rx = this->orx;
	if (ry != NULL) *ry = this->ory;
}

std::string Client::getName()
{
	return this->name;
}

void Client::set_pos(int x, int y, int z, int rx, int ry)
{
	this->x = x;
	this->y = y;
	this->z = z;
	this->rx = rx;
	this->ry = ry; // TODO SANITY CHECKS
}

void Client::set_pos_old(int x, int y, int z, int rx, int ry)
{
	this->ox = x;
	this->oy = y;
	this->oz = z;
	this->orx = rx;
	this->ory = ry; // TODO SANITY CHECKS
}

int Client::socket_ready()
{
	return SDLNet_SocketReady(this->socket);
}

TCPsocket Client::getSocket()
{
	return this->socket;
}

void Client::set_moved(bool val)
{
	this->moved = val;
}

void Client::get_last_block(int index, int* x, int* y, int* z, int* type)
{
	*x = this->last_block[index][0];
	*y = this->last_block[index][1];
	*z = this->last_block[index][2];
	if(type != NULL) *type = this->last_block[index][3];
}

void Client::set_last_block(int index, int x, int y, int z, int type)
{
	if (index == -1) {
		this->last_block[1][0] = this->last_block[0][0];
		this->last_block[1][1] = this->last_block[0][1];
		this->last_block[1][2] = this->last_block[0][2];
		this->last_block[1][3] = this->last_block[0][3];
		index = 0;
	}
	this->last_block[index][0] = x;
	this->last_block[index][1] = y;
	this->last_block[index][2] = z;
	this->last_block[index][3] = type;				
}
